package com.jimmyhsu.ecnudaowei.coursetable.face;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.jimmyhsu.ecnudaowei.MyApplication;
import com.jimmyhsu.ecnudaowei.R;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;


/**
 * Created by jimmyhsu on 2017/4/2.
 */

public class FaceDynamicDetectFragment extends Fragment implements SurfaceHolder.Callback, View.OnClickListener {
    private SurfaceView mPreviewView;
    private FloatingActionButton mShootBotton;
    private Camera camera;
    private SurfaceHolder mHolder;
    private ProgressBar mProgress;

    private MyHandler mHandler = new MyHandler(this);

    private static final String BUNDLE_RESULT = "bundle_result";



    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.frag_face_dynamic_detect, container, false);
        mPreviewView = (SurfaceView) v.findViewById(R.id.id_surface);
        mShootBotton = (FloatingActionButton) v.findViewById(R.id.id_shot);
        mProgress = (ProgressBar) v.findViewById(R.id.id_progress);
        return v;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mHolder = mPreviewView.getHolder();
        mHolder.addCallback(this);
        mShootBotton.setOnClickListener(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            camera = Camera.open(1); // 打开摄像头
            camera.setPreviewDisplay(holder); // 设置用于显示拍照影像的SurfaceHolder对象
            camera.setDisplayOrientation(90);
//            camera.setOneShotPreviewCallback(this);
            camera.startPreview(); // 开始预览
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        try {
            setSurfaceHeight(holder);
            Camera.Parameters parameters = camera.getParameters();
            parameters.setPictureFormat(ImageFormat.NV21); // 设置图片格式
            parameters.setPreviewFpsRange(20, 50);
            parameters.setJpegQuality(100); // 设置照片质量
            List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
            Camera.Size closelyPreSize = getCloselyPreSize(width, (int) (width * 4.0f / 3), supportedPreviewSizes);
            parameters.setPreviewSize(closelyPreSize.width, closelyPreSize.height);
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            parameters.setPictureSize(closelyPreSize.width, closelyPreSize.height); // 设置保存的图片尺寸
            camera.setParameters(parameters);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setSurfaceHeight(SurfaceHolder holder) {
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        wm.getDefaultDisplay().getMetrics(metrics);
        int width = metrics.widthPixels;
        holder.setFixedSize(width, (int) (width * 4.0f / 3));
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (camera != null) {
            camera.setOneShotPreviewCallback(null);
            camera.release(); // 释放照相机
            camera = null;
        }
    }

    protected Camera.Size getCloselyPreSize(int surfaceWidth, int surfaceHeight,
                                            List<Camera.Size> preSizeList) {

        int ReqTmpWidth;
        int ReqTmpHeight;
        // 当屏幕为垂直的时候需要把宽高值进行调换，保证宽大于高

        ReqTmpWidth = surfaceHeight;
        ReqTmpHeight = surfaceWidth;

        //先查找preview中是否存在与surfaceview相同宽高的尺寸
        for(Camera.Size size : preSizeList){
            if((size.width == ReqTmpWidth) && (size.height == ReqTmpHeight)){
                return size;
            }
        }

        // 得到与传入的宽高比最接近的size
        float reqRatio = ((float) ReqTmpWidth) / ReqTmpHeight;
        float curRatio, deltaRatio;
        float deltaRatioMin = Float.MAX_VALUE;
        Camera.Size retSize = null;
        for (Camera.Size size : preSizeList) {
            if (size.width < 1200) continue;
            curRatio = ((float) size.width) / size.height;
            deltaRatio = Math.abs(reqRatio - curRatio);
            if (deltaRatio < deltaRatioMin) {
                deltaRatioMin = deltaRatio;
                retSize = size;
            }
        }

        return retSize;
    }



//    private void parseResponseJson(String body) {
//        try {
//            JSONObject object = new JSONObject(body);
//            JSONArray faceArray = object.getJSONArray("faces");
//            if (faceArray.length() == 1) {
//                Log.e("haha", "face detected");
////                stopPreview();
//                JSONObject faceObject = faceArray.getJSONObject(0);
//                JSONObject faceRectangle = faceObject.getJSONObject("face_rectangle");
//                Face face = new Face(faceRectangle.getInt("width"),
//                        faceRectangle.getInt("top"),
//                        faceRectangle.getInt("left"),
//                        faceRectangle.getInt("height"),
//                        faceObject.getString("face_token"));
//                EventBus.getDefault().post(face);
//            }
//        } catch (JSONException e) {
//            e.printStackTrace();
//        }
//    }

    private void stopPreview() {
        camera.stopPreview();
    }

    private Bitmap rotateBitmap(Bitmap origin, float alpha) {
        if (origin == null) {
            return null;
        }
        int width = origin.getWidth();
        int height = origin.getHeight();
        Matrix matrix = new Matrix();
        matrix.setRotate(alpha);
        // 围绕原地进行旋转
        Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
        if (newBM.equals(origin)) {
            return newBM;
        }
        origin.recycle();
        return newBM;
    }


    private void restartPreview() {
        if (camera != null) {
            camera.startPreview();
            mProgress.setVisibility(View.GONE);
            ObjectAnimator animator = ObjectAnimator.ofFloat(mShootBotton, "translationY", 500, 0)
                    .setDuration(400);
            animator.setInterpolator(new AccelerateInterpolator());
            animator.start();
        }
    }

    @Override
    public void onClick(View v) {
        ObjectAnimator animator = ObjectAnimator.ofFloat(v, "translationY", 0, 500)
                .setDuration(400);
        animator.setInterpolator(new AccelerateInterpolator());
        animator.start();
        mProgress.setVisibility(View.VISIBLE);
        camera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                upload(data);
            }
        });
    }

    private void upload(final byte[] data) {
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
        Bitmap rotatedBm = rotateBitmap(bitmap, -90);

        try {
            File file = new File(Environment.getExternalStorageDirectory() + "/tempp.jpg");
            FileOutputStream out = new FileOutputStream(file);
            rotatedBm.compress(Bitmap.CompressFormat.JPEG, 80, out);
            out.flush();
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    ArrayList<String> path = new ArrayList<>();
                    path.add(Environment.getExternalStorageDirectory() + "/tempp.jpg");
                    // face++
                    String result = FaceUtils.detect(path.get(0));
                    // baidu
                    MyApplication app = MyApplication.getInstance(getContext());
                    JSONObject bdResponse = FaceUtils.getBaiduInstance().addUser(app.getName(), app.getName(),
                            "all", path);
                    if (bdResponse.toString().contains("error_code")) {
                        Toast.makeText(getContext(), "error: " + bdResponse.getString("error_msg"), Toast.LENGTH_SHORT).show();
                        restartPreview();
                        return;
                    }
                    Message msg = Message.obtain();
                    Bundle bundle = new Bundle();
                    bundle.putString(BUNDLE_RESULT, result);
                    msg.setData(bundle);
                    mHandler.sendMessage(msg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();



    }

    private static class MyHandler extends Handler {

        WeakReference<FaceDynamicDetectFragment> mReference;

        MyHandler(FaceDynamicDetectFragment fragment) {
            mReference = new WeakReference<>(fragment);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String facePPResult = msg.getData().getString(BUNDLE_RESULT);
            try {
                JSONObject obj = new JSONObject(facePPResult);
                JSONArray faces = obj.getJSONArray("faces");
                if (faces.length() == 1) {
                    JSONObject faceObj = faces.getJSONObject(0);
                    JSONObject faceRect = faceObj.getJSONObject("face_rectangle");
                    Face face = new Face(faceRect.getInt("width"),
                            faceRect.getInt("top"),
                            faceRect.getInt("left"),
                            faceRect.getInt("height"),
                            faceObj.getString("face_token"));
                    EventBus.getDefault().post(face);
//                    EventBus.getDefault().post(facePPResult);
                } else {
                    Toast.makeText(mReference.get().getContext(),
                            "检测到多张人脸，请重新拍摄~", Toast.LENGTH_SHORT).show();
                    mReference.get().restartPreview();
                }
            } catch (JSONException e) {
                e.printStackTrace();
                Toast.makeText(mReference.get().getContext(),
                        "网络异常，请重新拍摄", Toast.LENGTH_SHORT).show();
                mReference.get().restartPreview();
            }

        }
    }
}
